----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    10:45:43 10/03/2013 
-- Design Name: 
-- Module Name:    mult_32x32_control - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity mult_32x32_control is
	PORT (
	clk : IN STD_LOGIC;
	start : IN STD_LOGIC;
	selection1 : OUT STD_LOGIC_VECTOR(1 downto 0);
	selection2 : OUT STD_LOGIC_VECTOR(1 downto 0);
	shift_control : OUT STD_LOGIC;
	clear_latch : OUT STD_LOGIC;
	disable_changes : OUT STD_LOGIC;
	is_signed : IN STD_LOGIC; -- is this multiplication signed?
	
	-- signs of the 2 numbers, +ve is negative
	sign1 : IN STD_LOGIC;
	sign2 : IN STD_LOGIC;
	
	-- 
	adder_control : OUT STD_LOGIC_VECTOR(1 downto 0)
	);
end mult_32x32_control;

architecture Behavioral of mult_32x32_control is
	type POSSIBLE_STATES is (free, s1, s2, s3, s4);
	signal cur_state : POSSIBLE_STATES := free;
	
begin

	process(start, cur_state, sign1, sign2, is_signed)
	begin
		if (cur_state = free and start = '1') then
			-- init multiplication sequence
			if ((sign1 = '0' and sign2 = '0') or is_signed = '0') then
				clear_latch <= '1';
			else
				clear_latch <= '0';
			end if;
			shift_control <= '0';
			selection2 <= "00"; -- a0
			selection1 <= "10"; -- b0
			disable_changes <= '0';
			adder_control <= sign1&sign2;
		elsif (cur_state = free and start /= '1') then
			-- do nothing, idle state
			clear_latch <= '0';		-- don't care
			shift_control <= '0';	-- don't care
			selection2 <= "00";		-- don't care
			selection1 <= "00";		-- don't care
			disable_changes <= '1';	-- Do not update anything at this point
			adder_control <= "00";
		elsif (cur_state = s1) then
			clear_latch <= '0';
			shift_control <= '1';
			selection2 <= "01"; -- a1
			selection1 <= "10"; -- b0
			disable_changes <= '0';
			adder_control <= "00";
		elsif (cur_state = s2) then
			clear_latch <= '0';
			shift_control <= '0';
			selection2 <= "00"; -- a0
			selection1 <= "11"; -- b1
			disable_changes <= '0';
			adder_control <= "00";
		elsif (cur_state = s3) then
			clear_latch <= '0';
			shift_control <= '1';	-- 
			selection2 <= "01"; 		-- a1
			selection1 <= "11"; 		-- b1
			disable_changes <= '0';	--
			adder_control <= "00";
		else -- if (cur_state = s4) then
			-- This stage is only for addition, multiplication is not important here.
			clear_latch <= '0'; 		-- do not clear
			shift_control <= '0'; 	-- do not shift
			selection2 <= "01"; 		-- don't care
			selection1 <= "10"; 		-- don't care
			disable_changes <= '0'; -- allow changes to the latch
			adder_control <= "00";
		end if;
	end process;

	process (clk)
	begin
		if (clk'event and clk = '1') then
			if (cur_state = free and start = '1') then
				cur_state <= s1;
			elsif (cur_state = s1) then				
				cur_state <= s2;
			elsif (cur_state = s2) then
				cur_state <= s3;
			elsif (cur_state = s3) then
				cur_state <= free;
			elsif (cur_state = s4) then
				cur_state <= free;
			else 
				cur_state <= free;
			end if;
			
		end if;
	
	end process;

end Behavioral;

